#include <memory>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>

#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/projdefs.h"
#include "freertos/task.h"

#include "tasks.hpp"
#include "components.hpp"
// components
// #include "asrpro.h"
// #include "lcd.h"
// #include "lcd_ui.h"
// #include "mpu6050.h"
// #include "ultra.h"
// #include "utypes.h"
#include "asrpro.hpp"
#include "lcd.hpp"
#include "led.hpp"
#include "ultrasonic.hpp"
// void my_task(void *pvParameters) {
//     // 任务初始化（可选）
//     lcd_showString(100, 50, "Task created", BLUE, WHITE, 12, 0);

//     static int cnt = 0;
//     char buffer[32];

//     while (1) { // 任务主循环
//         snprintf(buffer, sizeof(buffer), "Task running: %d", cnt);
//         cnt++;
//         lcd_showString(30, 80, buffer, BLUE, WHITE, 16, 0);

//         mpu6050_data_t data;
//         esp_err_t err = mpu6050_read(&data);
//         if (err != ESP_OK) {
//             lcd_showString(30, 100, "Get MPU6050 data failed", BLUE, WHITE, 16, 0);
//         } else {
//             snprintf(buffer, sizeof(buffer), "accel_x: %f", data.accel_x);
//             lcd_showString(30, 100, buffer, BLUE, WHITE, 16, 0);
//             snprintf(buffer, sizeof(buffer), "accel_y: %f", data.accel_y);
//             lcd_showString(30, 120, buffer, BLUE, WHITE, 16, 0);
//             snprintf(buffer, sizeof(buffer), "accel_z: %f", data.accel_z);
//             lcd_showString(30, 140, buffer, BLUE, WHITE, 16, 0);
//         }

//         float distance = ultra_measureDistance();
//         sprintf(buffer, "Distance: %.2f cm", distance);
//         lcd_showString(30, 180, buffer, BLUE, WHITE, 16, 0);

//         vTaskDelay(pdMS_TO_TICKS(1000)); // 延时1秒（非阻塞）
//     }

//     // 若任务退出，需自行删除
//     vTaskDelete(NULL);
// }

extern "C" void app_main(void)
{
    // lcd_init();
    // lcd_showString(100, 20, "Task created", BLUE, WHITE, 16, 0);
    // mpu6050_init();
    // asrpro_init();
    // ultra_init();

// ------------------------------------
    // std::shared_ptr<Led> led = std::make_shared<Led>(GPIO_NUM_40, GPIO_NUM_41, GPIO_NUM_39, GPIO_NUM_38, 0);

    // std::shared_ptr<Lcd> lcd = std::make_shared<Lcd>(GPIO_NUM_14, GPIO_NUM_13, GPIO_NUM_12, GPIO_NUM_11,
    //     GPIO_NUM_10, GPIO_NUM_9);

    // lcd->showString(30, 30, "hello world", BLACK, WHITE, FONT_2412, 0);
    // lcd->showPicture(60, 60, 40, 40, gImage_1);

    // while (1) {
    //     led->allToggle();
    //     vTaskDelay(pdMS_TO_TICKS(1000));
    // }

    // std::shared_ptr<Asrpro> asrpro = std::make_shared<Asrpro>(UART_NUM_1, GPIO_NUM_17, GPIO_NUM_18, 9600);
    // bool success = true;
    // while (1) {
    //     uint8_t cmd = asrpro->recvCmd();
    //     printf("Recv cmd: %x\n", cmd);

    //     asrpro->sendAck(success);
    //     success = !success;
    // }
    // while (1) {
    //     asrpro->sendCmd(0x01);
    //     vTaskDelay(pdMS_TO_TICKS(2000));
    // }
    // uint8_t buffer[3];
    // while (1) {
    //     asrpro->recvData(buffer, sizeof(buffer));
    //     printf("%x %x %x\n",
    //         buffer[0], buffer[1], buffer[2]);

    //     buffer[0] = 0xCC;
    //     buffer[1] = 0x33;
    //     buffer[2] = 0x00;
    //     asrpro->sendData(buffer, sizeof(buffer));
    // }
    // while (1) {
    //     buffer[0] = 0xAA;
    //     buffer[1] = 0x55;
    //     buffer[2] = 0x01;
    //     asrpro->sendData(buffer, sizeof(buffer));
    //     vTaskDelay(pdMS_TO_TICKS(3000));
    // }

    // std::shared_ptr<Ultrasonic> ultra = std::make_shared<Ultrasonic>(GPIO_NUM_7, GPIO_NUM_6);
    // for (;;) {
    //     printf("Distance: %f cm\n", ultra->measureDistanceCM());
    //     vTaskDelay(pdMS_TO_TICKS(100));
    // }


// ------------------------------------
    // create new freertos task
    // xTaskCreate(my_task, "lcd_ui_task", 2048, NULL, 5, NULL);
    // xTaskCreate(asrpro_rx_task, "asrpro_rx_task", 2048, NULL, 5, NULL);

    // std::shared_ptr<Components> components = std::make_shared<Components>();
    // while (true) {
    //     components->led->allToggle();
    //     vTaskDelay(pdMS_TO_TICKS(2000));
    // }

    std::shared_ptr<Components> components = std::make_shared<Components>();
    std::shared_ptr<Tasks> tasks = std::make_shared<Tasks>(components);
    tasks->start();
}
